// Wrappers.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

template<class T>
class Ref;

template<class T>
class Ptr
{
public:
  Ptr(T* In)
  : mPtr(In)
  {
  }

  operator Ptr<const T>()
  {
    return Ptr<const T>(mPtr);
  }

  operator T*()
  {
    return mPtr;
  }

  Ptr operator =(Ptr Other)
  {
    mPtr = Other.mPtr;
    return *this;
  }

  template<class U>
  Ptr operator =(U Other)
  {
    mPtr = Other;
    return *this;
  }

  Ref<T> operator *();

  T* operator ->()
  {
    return mPtr;
  }

private:
  T* mPtr;
};

template<class T>
class Ref
{
public:
  Ref(T& In)
  : mRef(In)
  {
  }

  operator Ref<const T>()
  {
    return Ref<const T>(mRef);
  }

  operator T&()
  {
    return mRef;
  }

  Ref operator =(Ref Other)
  {
    mRef = Other.mRef;
    return *this;
  }

  template<class U>
  Ref operator =(U Other)
  {
    mRef = Other;
    return *this;
  }

private:
  T& mRef;
};

template<class T>
Ref<T> Ptr<T>::operator *()
{
  return Ref<T>(*mPtr);
}

#include <iostream>

void write(Ptr<const int> p)
{
  std::cout << *p << std::endl;
}

void write(Ref<const int> r)
{
  std::cout << r << std::endl;
}

int _tmain(int argc, _TCHAR* argv[])
{
  int i;
  Ptr<int> p = &i;
  Ptr<int> q = p;
  Ref<int> r = *p;
  Ref<const int> c = r;
  r = c;
  *p = 54321;
  
  write(p);

  return 0;
}

